
package controlleur;

import action.Action;
import action.DeplacerMouton;
import action.PoserBarriere;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import message.Information;
import modele.Berger;
import modele.Champ;
import modele.Mouton;
import modele.Partie;
import modele.Passage;

/**
 * Vérifie si les actions du joueur sont conforme aux reglès
 * Vérifie si un berger a gagné
 * 
 * @author DONG Xiangxiang Durand Rémi
 */
public class GestionJeu {
    
    /**
     * Vérifie si on peut poser une barriere sur le passage spécifié en parametre
     * @param partie en cours
     * @param berger qui fait l'action
     * @param passage où l'on souhaite déposer la barrière
     * @return true si on peut poser la barrière
     */
    public static boolean verifierPositionnerBarriere(Partie partie, Berger berger, Passage passage){
        boolean retour = false;
        // on vérifie si le berger peut jouer
        if(tourDuBerger(partie, berger)){
            // on vérifie si le berger peut effectuer cette action
            if(peutJouerAction(partie, berger, new PoserBarriere(null, null))){
                if(passage.isDisponible()){
                    retour = true;
                }
                else{
                    new Information("Le passage n'est pas disponnible.").afficher();
                }
            }
        }
        
        return retour;
    }
    
    /**
     * Vérifie si on peut déplacer le mouton vers un nouveau champ
     * @param partie en cours
     * @param berger berger qui fait l'action
     * @param mouton a déplcer
     * @param champsDestination futur champ
     * @return boolean
     */
    public static boolean verifierDeplacementMouton(Partie partie, Berger berger, Mouton mouton, Champ champsDestination){
        boolean resultat = false;
        
        // on vérifie si le berger peut jouer
        if(tourDuBerger(partie, mouton.getBerger())){
            // on vérifie si le joueur peut déplacer un mouton
            if(peutJouerAction(partie, berger, new DeplacerMouton(null, null))){
                // on vérifie si le mouton appartient bien au berger
                if(mouton.getBerger() == berger){
                    // on récupère le champ de départ
                    Champ champDepart = mouton.getPosition();

                    // on vérifie si le champs de destination est libre
                    if(champsDestination.isDisponible()){
                        // on vérifie s'il existe un passage
                        Passage passage = champDepart.retournePassageEnCommun(champsDestination);
                        if(passage != null){
                            // on vérifie si le passage est libre
                            if(passage.isDisponible()){
                                resultat = true;
                            }
                            // il y a une barrière
                            else{
                                new Information("Le passage n'est pas disponnible.").afficher();
                            }
                        }
                        // le passage n'existe pas
                        else{
                            new Information("Il n'existe aucun passage entre ces deux champs.").afficher();
                        }
                    }
                    // il y a déjà un mouton sur le champ de destination
                    else{
                        new Information("Il y a déjà un mouton sur le champs de destination.").afficher();
                    }
                }
                else{
                    new Information("Le mouton n'appartient pas au berger qui joue.").afficher();
                }
            }
        }
        return resultat;
    }
    
    
    public static boolean aGagne(Partie partie){
        boolean retour = false;
        
        // compte les moutons bloqués
        int nbMoutonsBloque = 0;
        
        for(int i = 0; i < partie.getMoutons().size(); i++){
            if(moutonEstBloque(partie.getMoutons().get(i))){
                nbMoutonsBloque++;
            }
        }
        
        // si tous les moutons sont bloqués
        if(partie.getMoutons().size() == nbMoutonsBloque){
            retour = true;
        }
        
        return retour;
    }
    
    /**
     * Vérifie si c'est au tour du berger spécifié en parametre
     * @param partie en cours
     * @param berger
     * @return 
     */
    public static boolean tourDuBerger(Partie partie, Berger berger){
        boolean retour = false;
        
        // si le berger à déjà joué
        if(partie.getDernierBerger().equals(berger)){
            // s'il reste des actions au berger
            if(partie.getNombreActionsDernierBerger() < 2){
                retour = true;
            }
            // le berger ne peut plus jouer
            else{
                new Information("Le berger a déjà joué ses deux actions.").afficher();
            }
        }
        // c'est un berger différent
        else{
            // on vérifie si le berger précédant à jouer ses 2 actions
            if(partie.getNombreActionsDernierBerger() == 2){
                retour = true;
            }
            else{
                new Information("Il reste une action au berger précédant.").afficher();
            }
        }
        
        return retour;
    }
    
    /**
     * Verifie si l'action précédente est différente de la nouvelle pour ce tour
     * @param partie en cours
     * @param berger qui veut jouer
     * @param action qui va être jouée
     * @return 
     */
    public static boolean peutJouerAction(Partie partie, Berger berger, Action action){
        boolean retour = false;
        
        // si c'est la première action pour ce tour on valide
        if(partie.getNombreActionsDernierBerger() == 0){
            retour =  true;
        }
        // le joueur a déjà joué une action
        else{
            int indiceDerniereAction = partie.getListeToursBerger().get(partie.getDernierBerger()).size() - 1;
            Action dernierAction = partie.getListeToursBerger().get(partie.getDernierBerger()).get(indiceDerniereAction);
                
            // on vérifie que la précédante action est différente de la nouvelle
            if(action != dernierAction){
                retour = true;
            }
            else{
                new Information("Le joueur a déjà effectué cette action pour ce tour.").afficher();
            }
        }        
        return retour;
    }
    
    public static boolean moutonEstBloque(Mouton mouton){
        // on suppose que le mouton est bloque
        boolean bloque = false;
        
        // on va parcourir les passages du champs ou se trouve le mouton
        Map passages = mouton.getPosition().getPassages();
        
        Set cles = passages.keySet();
        Iterator it = cles.iterator();
        
        // on compte le nombre de passage bloqué par une barriere
        int passagesBloque = 0;
        
        List<Passage> passagesDispo = new ArrayList<Passage>();
        
        while(it.hasNext()){
            Object positionPassage = it.next();
            Passage passageTemp = (Passage)passages.get(positionPassage);
            
            // le passage n'est disponnible
            if(!passageTemp.isDisponible()){
                passagesBloque++;
            }
            else{
                // on fait la liste des passages ouverts
                passagesDispo.add(passageTemp);
            }
        }
        
        // si tout les passages sont bloqués alors le mouton est bloqué
        if(passagesBloque == passages.size()){
            bloque = true;
        }
        // il y a au moins un passage de disponnible
        else{
            // on veut savoir s'il y a un mouton sur le champ opposé
            int i = 0;
            
            // on suppose que tous les champs sont occupés par un mouton
            boolean champsOccupe = true;
            
            while(champsOccupe && i < passagesDispo.size()){
                Champ champOppose = passagesDispo.get(i).champOppose(mouton.getPosition());
                
                // il y a un champ de disponnible
                if(champOppose.isDisponible()){
                    champsOccupe = false;
                }
                i++;
            }
            // si tous les champs sont occupés
            if(champsOccupe){
                bloque = true;
            }
        }
        
        return bloque;
    }
}
